﻿/****************************************************************************
** file: ToupCamCamera.cpp
** brief: 杭州图谱光电科技有限公司 显微镜相机支持代码
** Copyright (C) LiYuan
** Author: LiYuan
** E-Mail: 18069211#qq(.)com
** Version 0.0.1
** Last modified: 2019.07.20
** Modified By: LiYuan
****************************************************************************/


#include <QDebug>
#include <QDir>
#include <QSettings>
#include "CameraToupCam.h"

namespace Qly {

//QString CameraToupCamInfo::description()
//{
//    if(m_info.nTLayerType == MV_GIGE_DEVICE)
//    {
//        //QString modelName(m_info.SpecialInfo.stGigEInfo.chModelName);
//        //QString serialNumber(m_info.SpecialInfo.stGigEInfo.chSerialNumber);
//        //return modelName + " :" + serialNumber;
//    }
//    return "";
//}

//QList<IndustryCameraInfo*> CameraToupCamInfo::availableCameras()
//{
//    QList<IndustryCameraInfo*> info;
//    ToupcamDeviceV2 arr[TOUPCAM_MAX];
//    unsigned cnt = Toupcam_EnumV2(arr);
//    for (unsigned i = 0; i < cnt; ++i)
//    {
//        QString name = QString::fromWCharArray(arr[i].displayname);
//        QString id = QString::fromWCharArray(arr[i].id);
//        CameraToupCamInfo* p = new CameraToupCamInfo;
//        p->build(name, id);
//        info.append(p);
//    }
//    return info; // 这里会有内存
//}

CameraToupCam::CameraToupCam(QObject *parent)
    :IndustryCamera(parent),
      m_hDevHandle(nullptr),
	  pImageBuffer(nullptr)
{
    //connect(&dia, SIGNAL(exposureTimeAbsChanged(double)), this, SLOT(setExpoureTime(double)));
    //connect(&dia, SIGNAL(gammaChanged(double)), this, SLOT(setGamma(double)));
    //connect(&dia, SIGNAL(autoWhiteBalanceChanged(int)), this, SLOT(autoWhiteBalance(int)));

    //m_dialog = new CameraToupCamSettingDialog(this);
    m_dialog = new DialogCameraSetup(this);
    m_isLive = false;
//    m_dia->show();
}

CameraToupCam::~CameraToupCam()
{
    close();
    if(pImageBuffer)
    {
        delete [] pImageBuffer;
    }
    delete m_dialog;
}



QString CameraToupCam::cameraName()
{
    return m_name;
}

bool CameraToupCam::openCameraByID(QString id)
{
    ToupcamDeviceV2 arr[TOUPCAM_MAX];
    unsigned cnt = Toupcam_EnumV2(arr);
    m_hDevHandle = nullptr;
    for(int i = 0; i < cnt; i++)
    {
        QString name = QString::fromWCharArray(arr[i].displayname);
        if(id == name)
        {
            m_hDevHandle = Toupcam_OpenByIndex(i);
        }
    }

//    wchar_t id_array[100];
//    id.toWCharArray(id_array);

//    qDebug() << "openCameraByID id = " << id;
//    m_hDevHandle = Toupcam_Open(id_array);
//    qDebug() << "m_hDevHandle = " << m_hDevHandle;
    if (m_hDevHandle == nullptr)
    {
        qWarning("no Toupcam camera found!");
        return false;
    }
    int nRet = Toupcam_put_eSize(m_hDevHandle, 0);

    QSize v, min, max;
    imageSize(v, min, max);
    if(pImageBuffer)
    {
        delete [] pImageBuffer;
    }
    pImageBuffer = new uint8_t[v.width() * v.height() * 4];
    return nRet >= 0;
}

bool CameraToupCam::openByIdx(unsigned int index)
{
    ToupcamDeviceV2 arr[TOUPCAM_MAX];
    unsigned cnt = Toupcam_EnumV2(arr);
    if(cnt <= index)
    {
        return false;
    }
    if(m_hDevHandle)
    {
        close();
    }

    m_hDevHandle = Toupcam_OpenByIndex(index);
    if (m_hDevHandle == nullptr)
    {
        qWarning("Toupcam_OpenByIndex failed!");
        return false;
    }

    m_name = QString::fromWCharArray(arr[index].displayname);
    m_DeviceModelName = m_name;
    m_DeviceVendorName = "ToupTek Photonics";
    int nRet = Toupcam_put_eSize(m_hDevHandle, 0);

    QSize v, min, max;
    imageSize(v, min, max);
    if(pImageBuffer)
    {
        delete [] pImageBuffer;
    }
    pImageBuffer = new uint8_t[v.width() * v.height() * 4];
    Toupcam_put_Option(m_hDevHandle, TOUPCAM_OPTION_BYTEORDER, 1);
    CameraToupCamImageProcessing * p = new CameraToupCamImageProcessing;
    p->m_hDevHandle = m_hDevHandle;
    m_cameraImageProcessing = p;
    m_dialog->initNodeInfo();
    return nRet >= 0;
}

bool CameraToupCam::openDefaultCamera()
{
    return openByIdx(0);
}


AVPixelFormat CameraToupCam::getBayer8Patern()
{
    return AV_PIX_FMT_GRAY8;
}

bool CameraToupCam::setPixelType(AVPixelFormat type)
{
    if (m_hDevHandle == nullptr)
    {
        return false;
    }

    //unsigned int enValue = PixelType_Gvsp_Mono8;
    switch (type)
    {
    case AV_PIX_FMT_GRAY8:
        Toupcam_put_Chrome(m_hDevHandle, true);
        break;
    default:
        Toupcam_put_Chrome(m_hDevHandle, false);
        break;
    }
    return true;
}

void CameraToupCam::close()
{
    if (m_hDevHandle == nullptr)
    {
        return;
    }
    stopGrabbing();
    Toupcam_Close(m_hDevHandle);
    m_hDevHandle = nullptr;
	m_name.clear();
}

bool CameraToupCam::saveDeviceControlSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;

//        settings.setValue("DeviceControl/DeviceVendorName", DeviceVendorName);
//       settings.setValue("DeviceControl/DeviceModelName", DeviceModelName);
//        settings.setValue("DeviceControl/DeviceManufacturerInfo", DeviceManufacturerInfo);
//        settings.setValue("DeviceControl/DeviceVersion", DeviceVersion);
//        settings.setValue("DeviceControl/DeviceFirmwareVersion", DeviceFirmwareVersion);
//        settings.setValue("DeviceControl/DeviceSerialNumber", DeviceSerialNumber);
//        settings.setValue("DeviceControl/DeviceID", DeviceID);
//        settings.setValue("DeviceControl/DeviceUserID", DeviceUserID);
//       settings.setValue("DeviceControl/UserID", UserID);
    return false;
}

bool CameraToupCam::saveAnalogControlSettings(QSettings &settings)
{
    if( m_hDevHandle == nullptr ) return false;
    return m_cameraImageProcessing->writeSettings(settings);
}

bool CameraToupCam::saveAcquisitionControlSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;

//        settings.setValue("AcquisitionControl/AcquisitionFrameRate", static_cast<double>(struFloatValue.fCurValue));

//        settings.setValue("AcquisitionControl/AutoExposure", struEnumValue.nCurValue == MV_EXPOSURE_AUTO_MODE_CONTINUOUS);
    
//        settings.setValue("AcquisitionControl/AutoExposureTimeLower", struIntValue.nCurValue);
    
    
//        settings.setValue("AcquisitionControl/AutoExposureTimeUpper", struIntValue.nCurValue);
    
    double us;
    exposureTime(us);
    settings.setValue("AcquisitionControl/ExposureTime", us);
    

    //Get bool parameters
    // bool bValue = 0;
    // nRet = MV_CC_GetBoolValue(m_hDevHandle, "HDREnable", &bValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("AcquisitionControl/HDREnable", bValue);
    // }

    // nRet = MV_CC_GetIntValue(m_hDevHandle, "HDRSelector", &struIntValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("AcquisitionControl/HDRSelector", struIntValue.nCurValue);
    // }

    // nRet = MV_CC_GetIntValue(m_hDevHandle, "HDRShuter", &struIntValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("AcquisitionControl/HDRShuter", struIntValue.nCurValue);
    // }

    // nRet = MV_CC_GetFloatValue(m_hDevHandle, "HDRGain", &struFloatValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("AcquisitionControl/HDRGain",static_cast<double> (struFloatValue.fCurValue));
    // }
    return false;

}

bool CameraToupCam::loadAcquisitionControlSettings(QSettings &settings)
{
    bool ok;
    if( m_hDevHandle == nullptr ) return false;
    double fValue = settings.value("AcquisitionControl/FrameRate", 20.0).toDouble(&ok);
    if(ok)
    {
        setFrameRate(fValue);
    }

    bool on = settings.value("AcquisitionControl/AutoExposure", false).toBool();
    if(on)
    {
        setExposureTimeMode(CONTINUOUS);
    }
    else
    {
        fValue = settings.value("AcquisitionControl/ExposureTime", 1000).toDouble();
        qDebug() << "AcquisitionControl/ExposureTime = " << fValue;
        setExposureTime(fValue);
    }
    return true;
}

bool CameraToupCam::saveTLayerControlSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;
    // 获取设备信息
    // MV_CC_DEVICE_INFO struDeviceInfo;
    // memset(&struDeviceInfo, 0, sizeof(MV_CC_DEVICE_INFO));
    // int nRet = MV_CC_GetDeviceInfo(m_hDevHandle, &struDeviceInfo);
    // if (MV_OK == nRet)
    // {
        // settings.setValue( "TLayerControl/GevVersionMajor", struDeviceInfo.nMajorVer );
        // settings.setValue( "TLayerControl/GevVersionMinor", struDeviceInfo.nMinorVer );
        // settings.setValue( "TLayerControl/MacAddrHigh", struDeviceInfo.nMacAddrHigh );
        // settings.setValue( "TLayerControl/MacAddrLow", struDeviceInfo.nMacAddrLow );
        // settings.setValue( "TLayerControl/TLayerType", struDeviceInfo.nTLayerType );
    // }

    return false;
}

bool CameraToupCam::savePixelFormatSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;
    //获取相机图像的像素格式
    // MVCC_ENUMVALUE struEnumValue = {0};
    // int nRet = MV_CC_GetPixelFormat(m_hDevHandle, &struEnumValue);
    // if (MV_OK == nRet)
    // {
        // switch (struEnumValue.nCurValue)
        // {
        // case PixelType_Gvsp_Mono8:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::Mono8);
            // break;
        // case PixelType_Gvsp_BayerBG8:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::BayerBG8);
            // break;
        // case PixelType_Gvsp_BayerGB8:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::BayerGB8);
            // break;
        // case PixelType_Gvsp_BayerRG8:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::BayerRG8);
            // break;
        // case PixelType_Gvsp_BayerGR8:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::BayerGR8);
            // break;
        // case PixelType_Gvsp_RGB8_Packed:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::RGB24);
            // break;
        // case PixelType_Gvsp_RGBA8_Packed:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::RGB32);
            // break;
        // case PixelType_Gvsp_YUV422_Packed:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::YUV422);
            // break;
        // case PixelType_Gvsp_YUV422_YUYV_Packed:
            // settings.setValue("Basic/PixelFomat", IndustryCamera::YUYV);
            // break;
        // }
    // }
    return false;
}

bool CameraToupCam::loadPixelFormatSettings(QSettings &settings)
{
    if( m_hDevHandle == nullptr ) return false;
    AVPixelFormat ptValue = static_cast<AVPixelFormat> (settings.value("Basic/PixelFomat", AV_PIX_FMT_GRAY8).toInt() );
    return setPixelType(ptValue);
}

bool CameraToupCam::saveCameraSizeSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;

    //获取相机图像基本信息
    // MV_IMAGE_BASIC_INFO mstruBasicInfo = {0};
    // int nRet = MV_CC_GetImageInfo(m_hDevHandle, &mstruBasicInfo);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("Basic/Width", mstruBasicInfo.nWidthValue);
        // settings.setValue("Basic/Height", mstruBasicInfo.nHeightValue);
    // }

    //获取AOI偏移量X值
    // MVCC_INTVALUE struIntValue = {0};
    // nRet = MV_CC_GetAOIoffsetX(m_hDevHandle, &struIntValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("Basic/OffsetX", struIntValue.nCurValue);
    // }
    // nRet = MV_CC_GetAOIoffsetY(m_hDevHandle, &struIntValue);
    // if (MV_OK == nRet)
    // {
        // settings.setValue("Basic/OffsetY", struIntValue.nCurValue);
    // }
    return false;
}

bool CameraToupCam::loadCameraSizeSettings(QSettings &settings)
{
    Q_UNUSED(settings);
    if( m_hDevHandle == nullptr ) return false;
    // int nValue = settings.value("Basic/OffsetX", 0).toInt();
    // int nRet = MV_CC_SetAOIoffsetX(m_hDevHandle, nValue);
    // qDebug() << "Basic/OffsetX = " << nValue;

    // nValue = settings.value("Basic/OffsetY", 0).toInt();
    // nRet = MV_CC_SetAOIoffsetY(m_hDevHandle, nValue);
    // qDebug() << "Basic/OffsetY = " << nValue;

    // nValue = settings.value("Basic/Width", 0).toInt();
    // if(nValue)
    // {
        // nRet = MV_CC_SetWidth(m_hDevHandle, nValue);
        // qDebug() << "Basic/Width = " << nValue;
    // }

    // nValue = settings.value("Basic/Height", 0).toInt();
    // if(nValue)
    // {
        // nRet = MV_CC_SetHeight(m_hDevHandle, nValue);
        // qDebug() << "Basic/Height = " << nValue;
    // }
    return true;
}

bool CameraToupCam::saveSettings(QSettings &settings)
{
    saveTLayerControlSettings(settings);
    saveDeviceControlSettings(settings);
    saveAcquisitionControlSettings(settings);
    savePixelFormatSettings(settings);
    saveCameraSizeSettings(settings);
    return saveAnalogControlSettings(settings);
}

bool CameraToupCam::loadAnalogControlSettings(QSettings &settings)
{
    if( m_hDevHandle == nullptr ) return false;
    return m_cameraImageProcessing->loadSettings(settings);
}

bool CameraToupCam::loadSettings(QSettings &settings)
{
    loadCameraSizeSettings(settings);
    loadAcquisitionControlSettings(settings);
    loadAnalogControlSettings(settings);
    return true;
}

bool CameraToupCam::saveSettingsToFile(QString fileName)
{
    if (nullptr == m_hDevHandle)
    {
        return false;
    }
    fileName.replace('\\','/');
    int pos = fileName.lastIndexOf('/');
    QString path(fileName.left(pos));
    QDir dir;
    dir.mkpath(path);

    //TODO:应该先判读这个路径是否存在。文件名是否是 ini 结尾的。
    if(fileName.endsWith(".ini", Qt::CaseInsensitive))
    {
        QSettings settings( fileName, QSettings::IniFormat, this );
        return saveSettings(settings);
    }

    return false;
}

bool CameraToupCam::loadSettingsFromFile(QString fileName)
{
    if (m_hDevHandle == nullptr)
    {
        return false;
    }
    fileName.replace('\\','/');
    int pos = fileName.lastIndexOf('/');
    QString path(fileName.left(pos));
    QDir dir;
    dir.mkpath(path);

    if( dir.exists(fileName) == false)
    {
        qWarning() << "Camera.ini not exist";
        return false;
    }

    if(fileName.endsWith(".ini", Qt::CaseInsensitive))
    {
        QSettings settings( fileName, QSettings::IniFormat, this );
        return loadSettings(settings);
    }
    return false;
}

bool CameraToupCam::isLive()
{
    return m_isLive;
}

bool CameraToupCam::startGrabbing()
{
    m_imageCount = 0;
    if (m_hDevHandle == nullptr)
    {
        qDebug() << "error: OpenDevice fail";
        return false;
    }
    int nRet = Toupcam_StartPullModeWithCallback(m_hDevHandle, ImageCallBack, this);
    if (nRet < 0)
    {
        qDebug() << "error: Toupcam_StartPullModeWithCallback fail";
        return false;
    }
    m_isLive = true;
    return true;
}

bool CameraToupCam::stopGrabbing()
{
    if (nullptr == m_hDevHandle)
    {
        return false;
    }
    int nRet = Toupcam_Stop(m_hDevHandle);
    if (nRet < 0)
    {
        qDebug() << "error: Toupcam_Stop fail";
        return false;
    }
    m_isLive = false;
    return true;
}

bool CameraToupCam::getFlip(bool &von, bool &hon)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    int on1, on2;
    int nRet = Toupcam_get_VFlip(m_hDevHandle, &on1);
    nRet = Toupcam_get_HFlip(m_hDevHandle, &on2);

    von = on1;
    hon = on2;
    return nRet >= 0;
}

bool CameraToupCam::setVFlip(bool on)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    qDebug() << "Toupcam_put_VFlip";
	int nRet = Toupcam_put_VFlip(m_hDevHandle, on);
    return nRet >= 0;
	
}

bool CameraToupCam::setHFlip(bool on)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
	int nRet = Toupcam_put_HFlip(m_hDevHandle, on);
    return nRet >= 0;
}
	

bool CameraToupCam::showVCDPropertyPage()
{
    //m_dialog->initNodeInfo();
    m_dialog->show();
    return false;
}

bool CameraToupCam::setHeartBeatTimeout(int ms)
{
    Q_UNUSED(ms);
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    
    return false;
}

QRect CameraToupCam::AOIRegion()
{
    if (m_hDevHandle == nullptr)
    {
         return QRect();
    }
    unsigned xOffset, yOffset, xWidth, yHeight;
    Toupcam_get_Roi(m_hDevHandle, &xOffset, &yOffset, &xWidth, &yHeight);
    return QRect(xOffset, yOffset, xWidth, yHeight);
}

bool CameraToupCam::setAOIRegion(unsigned int xOffset, unsigned int yOffset, unsigned int xWidth, unsigned int yHeight)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    xOffset = (xOffset >> 1) << 1; // 必须是偶数
    yOffset = (yOffset >> 1) << 1; // 必须是偶数
    xWidth = (xWidth >> 4) << 4; // 必须是 16 的整数倍
    yHeight = (yHeight >> 4) << 4; // 必须是 16 的整数倍

    int nRet = Toupcam_put_Roi(m_hDevHandle, xOffset, yOffset, xWidth, yHeight);
    return nRet >= 0;

}
bool CameraToupCam::setAOIRegion(QRect rect)
{
    unsigned int xOffset = static_cast<unsigned int>(rect.left());
    unsigned int yOffset = static_cast<unsigned int>(rect.top());
    unsigned int xWidth = static_cast<unsigned int>(rect.width());
    unsigned int yHeight = static_cast<unsigned int>(rect.height());

    return setAOIRegion(xOffset, yOffset, xWidth, yHeight);
}

bool CameraToupCam::frameRate(double &fps)
{
    fps = 0;
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    ///TODO frameRate
    return false;
}

bool CameraToupCam::setFrameRate(double fps)
{
    Q_UNUSED(fps);
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    /// TODO setFrameRate

    return false;
}


bool CameraToupCam::autoExposureTimeLowerLimitRange(int &nMin, int &nMax, int &nValue)
{
    Q_UNUSED(nMin);
    Q_UNUSED(nMax);
    Q_UNUSED(nValue);
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    //Get int parameter
    // MVCC_INTVALUE struIntValue = {0};

    // int nRet = MV_CC_GetIntValue(m_hDevHandle, "AutoExposureTimeLowerLimit", &struIntValue);
    // if (MV_OK != nRet)
    // {
        // qWarning() << "error: Get AutoExposureTimeLowerLimit fail";
        // return false;
    // }
    // nMin = struIntValue.nMin;
    // nMax = struIntValue.nMax;
    // nValue = struIntValue.nCurValue;
    return true;
}

bool CameraToupCam::autoExposureTimeUpperLimitRange(int &nMin, int &nMax, int &nValue)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    double min, max, value;
    exposureTimeRange(min, max, value);
    nMin = static_cast<int>(min);
    nMax = static_cast<int>(max);
	nValue = 350000;
    return true;
}


bool CameraToupCam::exposureTimeRange(double &min, double &max, double &fValue)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    int ret;
    unsigned nMin;
    unsigned nMax;
    unsigned nDef;
    ret = Toupcam_get_ExpTimeRange(m_hDevHandle, &nMin, &nMax, &nDef);
	ret = Toupcam_get_ExpoTime(m_hDevHandle, &nDef);
    min = nMin;
    max = nMax;
    fValue = nDef;
   // qDebug() << "expo = " << fValue;
    return ret >= 0;
}

bool CameraToupCam::setResolutionByIdx(int N)
{
    qDebug() << "setResolutionByIdx";
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    if(N < 0) return false;
    stopGrabbing();
    HRESULT ret = Toupcam_put_eSize(m_hDevHandle, N);
    startGrabbing();
       qDebug() << "Toupcam_put_eSize N = " << N;
    return ret >= 0;

}

QStringList CameraToupCam::resolution()
{
    qDebug() << "resolution";
    if (m_hDevHandle == nullptr)
    {
         return QStringList();
    }
    int N = Toupcam_get_ResolutionNumber(m_hDevHandle);
    qDebug() << "Toupcam_get_ResolutionNumber = " << N;
    int width, height;

    QStringList list;
    for(int i = 0; i < N; i++)
    {
        Toupcam_get_Resolution(m_hDevHandle, i, &width, &height);
        list << QString("%1, %2").arg(width).arg(height);
    }
    return list;
}

bool CameraToupCam::imageSize(QSize &size, QSize &max, QSize &min)
{
    if (m_hDevHandle == nullptr)
    {
         return false;
    }
    int width, height;
	Toupcam_get_Size(m_hDevHandle, &width, &height);
    
    size.setHeight(height);
    size.setWidth(width);
	
    int N = Toupcam_get_ResolutionNumber(m_hDevHandle);
	Toupcam_get_Resolution(m_hDevHandle, 0, &width, &height);
    max.setHeight(height);
    max.setWidth(width);
	
    Toupcam_get_Resolution(m_hDevHandle, static_cast<unsigned>(N - 1), &width, &height);
	
    min.setHeight(height);
    min.setWidth(width);
    return true;
}

bool CameraToupCam::setExposureTimeMode(AutoExposureMode mode)
{
    int nRet;
    switch (mode) {
    case OFF:
        nRet = Toupcam_put_AutoExpoEnable(m_hDevHandle, false);
        break;
    case ONCE:
        qDebug() << "error: CameraToupCam::setExposureTimeMode(ONCE) ONCE is not supported";
        return false;
        break;
    case CONTINUOUS:
         nRet = Toupcam_put_AutoExpoEnable(m_hDevHandle, true);
        break;
    }
    if (nRet < 0)
    {
        qDebug() << "error: setExposureTimeMode fail";
        return false;
    }
    return true;
}

bool CameraToupCam::exposureTimeMode(AutoExposureMode &mode)
{
    int bAutoExposure;
    int nRet = Toupcam_get_AutoExpoEnable(m_hDevHandle, &bAutoExposure);
    if (nRet < 0)
    {
        qDebug() << "error: Toupcam_get_AutoExpoEnable fail";
        return false;
    }
    if(bAutoExposure) mode = CONTINUOUS;
    else mode = OFF;
    return true;
}


bool CameraToupCam::exposureTime(double &us)
{

	unsigned Time;
    int nRet = Toupcam_get_ExpoTime(m_hDevHandle, &Time);
    qDebug() << "Toupcam_get_ExpoTime = " << Time;
    if (nRet < 0)
    {
        qDebug() << "error: GetExposureTime fail";
        return false;
    }
    us = Time;
    return true;
}

bool CameraToupCam::setExposureTime(double us)
{
    double min, max, value;
    int nRet = exposureTimeRange(min, max, value);
    if (nRet < 0)
    {
        qDebug() << "error: GetExposureRange fail";
        return false;
    }
	value = us;
    value = qBound(min, value, max);
    nRet = Toupcam_put_ExpoTime(m_hDevHandle, value);
    if (nRet < 0)
    {
        qDebug() << "error: Set ExposureTime fail";
        return false;
    }
    qDebug() << "Exposure Time = " << value;
    return true;
}

/*
void __stdcall CameraToupCam::ExceptionCallBack(unsigned int nMsgType, void *pUser)
{
    CameraToupCam *camera = static_cast<CameraToupCam *> (pUser);
    if(0x00008001 == nMsgType)
    {
        emit camera->deviceLost();
    }
}*/

void OnEventImage(CameraToupCam *camera)
{
    unsigned width, height;
    Toupcam_PullImage(camera->m_hDevHandle, nullptr, 24, &width, &height);
    QSize size(static_cast<int>(width), static_cast<int>(height));
    Toupcam_PullImage(camera->m_hDevHandle, camera->pImageBuffer, 24, nullptr, nullptr);
    camera->m_imageCount ++;
    AVPixelFormat format = AV_PIX_FMT_BGR24;
    VideoFrame frame(camera->pImageBuffer, size, format);
    frame.setExtraInfo(camera->m_imageCount++, QDateTime::currentDateTime());
    emit camera->videoFrameReady(frame);
   // emit camera->RGB24ImageChanged(camera->pImageBuffer, size);
    //emit camera->ImageDataChanged(camera->pImageBuffer, size, format);
}

void OnEventSnap(CameraToupCam *camera)
{
    unsigned width, height;
    Toupcam_PullStillImage(camera->m_hDevHandle, nullptr, 24, &width, &height);
    QSize size(static_cast<int>(width), static_cast<int>(height));
    Toupcam_PullStillImage(camera->m_hDevHandle, camera->pImageBuffer, 24, nullptr, nullptr);
    AVPixelFormat format = AV_PIX_FMT_BGR24;
    VideoFrame frame(camera->pImageBuffer, size, format);
    frame.setExtraInfo(camera->m_imageCount++, QDateTime::currentDateTime());
    emit camera->videoFrameReady(frame);
    //emit camera->RGB32ImageChanged(camera->pImageBuffer, size);
    //emit camera->ImageDataChanged(camera->pImageBuffer, size, format);
}
void OnEventExpo(CameraToupCam *camera)
{
    //double dMin, dMax, dValue;
    //camera->exposureRange(dMin, dMax, dValue);
    camera->m_dialog->updateAutoExposureValue();

    //camera->m_dialog->setExposureTime(dValue);
}

void OnEventTempTint(CameraToupCam *camera)
{
    int nTemp, nTint;
//    camera->imageProcessing()->whiteBalanceTempTint(nTemp, nTint);
//    camera->m_dialog->setWhiteBalanceTempTint(nTemp, nTint);
}
void __stdcall CameraToupCam::ImageCallBack(unsigned nEvent, void* pCallbackCtx)
{
	switch (nEvent)
	{
	case TOUPCAM_EVENT_ERROR:
		//OnEventUsbError();
		break;
	case TOUPCAM_EVENT_EXPOSURE:
        OnEventExpo(reinterpret_cast<CameraToupCam *> (pCallbackCtx));
		break;
	case TOUPCAM_EVENT_TEMPTINT:
        OnEventTempTint(reinterpret_cast<CameraToupCam *> (pCallbackCtx));
		break;
	case TOUPCAM_EVENT_IMAGE:
        OnEventImage(reinterpret_cast<CameraToupCam *> (pCallbackCtx));
		break;
	case TOUPCAM_EVENT_STILLIMAGE:
        OnEventSnap(reinterpret_cast<CameraToupCam *> (pCallbackCtx));
		break;
	}
}

} //namespace Qly


